package com.lsc.learn.mybatisplus.utils;

import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class BeanUtils {
	private static Map<Class<?>, SerializedLambda> CLASS_LAMDBA_CACHE = new ConcurrentHashMap<>();

	/***
	 * 转换方法引用为属性名
	 * 
	 * @param fn
	 * @return
	 */
	public static <T> String convertToFieldName(IGetter<T> fn) {
		SerializedLambda lambda = getSerializedLambda(fn);
		String methodName = lambda.getImplMethodName();
		String prefix = null;
		if (methodName.startsWith("get")) {
			prefix = "get";
		} else if (methodName.startsWith("is")) {
			prefix = "is";
		}
		if (prefix == null) {
			log.warn("无效的getter方法: " + methodName);
		}
		// 截取get/is之后的字符串并转换首字母为小写（S为diboot项目的字符串工具类，可自行实现）
        return toLowerCaseFirstOne(methodName.replace(prefix, ""));
	}

	public static <T, U> String convertToFieldName(ISetter<T, U> fn) {
		SerializedLambda lambda = getSerializedLambda(fn);
		String methodName = lambda.getImplMethodName();
		if (!methodName.startsWith("set")) {
			log.warn("无效的setter方法：" + methodName);
		}
        return toLowerCaseFirstOne(methodName.replace("set", ""));
	}

	/**
	 * 关键在于这个方法
	 */
	public static SerializedLambda getSerializedLambda(Serializable fn) {
		SerializedLambda lambda = CLASS_LAMDBA_CACHE.get(fn.getClass());
		if (lambda == null) {
			try {
				Method method = fn.getClass().getDeclaredMethod("writeReplace");
				method.setAccessible(Boolean.TRUE);
				lambda = (SerializedLambda) method.invoke(fn);
				CLASS_LAMDBA_CACHE.put(fn.getClass(), lambda);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return lambda;
	}
	
	private static String toLowerCaseFirstOne(String str) {
		if (Character.isLowerCase(str.charAt(0))) {
            return str;
        } else {
            return (new StringBuilder()).append(Character.toLowerCase(str.charAt(0))).append(str.substring(1)).toString();
        }
	}

	public static void main(String[] args) {
		String getName = BeanUtils.convertToFieldName(Person::getName);
		System.out.println(getName);
		String setName = BeanUtils.convertToFieldName(Person::setId);
		System.out.println(setName);
	}
}
